/*
 * @Descripttion:
 * @version:
 * @Author: lfzxs@qq.com
 * @Date: 2023-06-15 11:25:23
 * @LastEditors: lfzxs@qq.com
 * @LastEditTime: 2023-06-21 09:58:31
 */
package loader

import (
	"io/ioutil"
	"net/url"
	"strings"

	"golang.org/x/exp/slog"
	"gopkg.in/yaml.v2"
)

type YmlLoader struct {
}

func MakeCfgItem(key,value any)CfgItem{
	cfgItem := CfgItem{
		Key:   key,
		Value: value,
	}
	return cfgItem
}


func MapSliceToCfgSlice(source yaml.MapSlice)(result CfgSlice){
	result = CfgSlice{}

	for _, item := range source {
		switch value := item.Value.(type) {
			case string: // item.Value 是字符串类型
			cfgItem := MakeCfgItem(item.Key,item.Value)  
			
			slog.Debug("yml项["+item.Key.(string)+"]", cfgItem)
			result = append(result, cfgItem)


			case yaml.MapSlice:
				subSlice := MapSliceToCfgSlice(value)
				cfgItem := MakeCfgItem(item.Key,subSlice)  
				slog.Debug("yml项["+item.Key.(string)+"]", subSlice)
				result = append(result, cfgItem)

			case []interface{}: // []interface{} 类型
				var vals []interface{}
				for _, subint := range value {
					vs, ok := subint.(string)
					if ok {
						vals = append(vals, vs)
					}
	
					vMapSlice, ok := subint.(yaml.MapSlice)
					if ok {
						subSlice := MapSliceToCfgSlice(vMapSlice)
						vals = append(vals, subSlice)
					}
				}
				slog.Debug("yml项["+item.Key.(string)+"]", vals)
				cfgItem := MakeCfgItem(item.Key,vals)  
				result = append(result, cfgItem)

			default:
				cfgItem := MakeCfgItem(item.Key,item.Value)  
			
				slog.Debug("yml项["+item.Key.(string)+"]", cfgItem)
				result = append(result, cfgItem)
		}
	}
	return  result
}

func (sf *YmlLoader) LoadFromByte(data []byte) (cfgs CfgSlice,err error) {
	// 要有顺序,否则变量解析会出错
	cnf := yaml.MapSlice{}

	err = yaml.Unmarshal(data, &cnf)
	if err != nil {
		slog.Error("yaml 解包出错!", err)
		return nil,err
	}

	cfgs = MapSliceToCfgSlice(cnf)
	
	slog.Debug("yml内容:", cfgs)
	return cfgs,err

}

func (sf *YmlLoader) LoadFromURI(uri string) (cfg CfgSlice,err error) {
	//[协议名]://[用户名]:[密码]@[服务器地址]:[服务器端口号]/[路径]?[查询字符串]#[片段ID]
	slog.Debug("加载文件",uri)
	parsedURL, err := url.Parse(uri)
	if err != nil {
		slog.Error("解析URI出错:", err)
		return
	}

	scheme := strings.ToLower(parsedURL.Scheme)

	switch scheme {
		case "file":
			filePath := parsedURL.Path
			content, err := ioutil.ReadFile(filePath)
			if err != nil {
				return nil,err
			}
			return sf.LoadFromByte(content)
	}


	return
}
